package org.totoro.concurrent.sync.mark_word.state;

import lombok.SneakyThrows;
import org.totoro.concurrent.sync.mark_word.MarkWordStrategyAbs;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * 偏向锁
 * <p>
 * vm： -XX:-UseCompressedOops -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
 * <p>
 * |------------------------------------------------------------------------------|--------------------|
 * |                                  Mark Word (64 bits)                         |       State        |
 * |------------------------------------------------------------------------------|--------------------|
 * | unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 |       Normal       | (01)无锁
 * |------------------------------------------------------------------------------|--------------------|
 * | thread:54 |       epoch:2        | unused:1 | age:4 | biased_lock:1 | lock:2 |       Biased       | (01)偏向锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                       ptr_to_lock_record:62                         | lock:2 | Lightweight Locked | (00)轻量级锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                     ptr_to_heavyweight_monitor:62                   | lock:2 | Heavyweight Locked | (10)重量级锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                                                                     | lock:2 |    Marked for GC   | (11)GC标记
 * |------------------------------------------------------------------------------|--------------------|
 * <p>
 *
 * <p>
 * |-------------------------------------------------------|--------------------|
 * |                  Mark Word (32 bits)                  |       State        |
 * |-------------------------------------------------------|--------------------|
 * | identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 |       Normal       |
 * |-------------------------------------------------------|--------------------|
 * |  thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 |       Biased       |
 * |-------------------------------------------------------|--------------------|
 * |               ptr_to_lock_record:30          | lock:2 | Lightweight Locked |
 * |-------------------------------------------------------|--------------------|
 * |               ptr_to_heavyweight_monitor:30  | lock:2 | Heavyweight Locked |
 * |-------------------------------------------------------|--------------------|
 * |                                              | lock:2 |    Marked for GC   |
 * |-------------------------------------------------------|--------------------|
 *
 * @author daocr
 * @date 2020/3/16
 */
public class BiasedStrategy extends MarkWordStrategyAbs {

    public BiasedStrategy(Object instance) {
        super(instance);
    }

    @Override
    protected void printType(List<MarkWord> markWords) throws InterruptedException {


        String easyRead = getEasyRead(markWords);
        BigInteger lock = new BigInteger(easyRead.replace(" ", ""), 2);

        BigInteger easyReadBigInteger = new BigInteger(easyRead.replace(" ", ""), 2);

        String lock_str = findOffsetCode(easyReadBigInteger, LOCK_OFFSET);
        String biased_lock_str = findOffsetCode(easyReadBigInteger, BIASED_LOCK_OFFSET);
        String age_offset_str = findOffsetCode(easyReadBigInteger, AGE_OFFSET);
        String epoch_offset_str = findOffsetCode(easyReadBigInteger, EPOCH_OFFSET);
        String thread_offset_str = findOffsetCode(easyReadBigInteger, THREAD_OFFSET);


        System.out.println("lock :" + lock_str + "\tbiased_lock：" + biased_lock_str + "\tage_offset：" + age_offset_str + "\tepoch_offset：" + epoch_offset_str + "\tthread offset :" + thread_offset_str);


        BigInteger bigInteger = new BigInteger(thread_offset_str, 2);
        System.out.println(bigInteger.longValue() + " hex : " + Long.toHexString(bigInteger.longValue()));
    }

    @SneakyThrows
    @Override
    public void print() {
        new Thread(() -> {
            try {
                int sum = 0;
                for (int i = 0; i < 10000000; i++) {
                    synchronized (instance) {
                        sum++;

                    }
                }


                Long id = Thread.currentThread().getId();
                System.out.println("thead id：" + id + "\thex ：" + Long.toHexString(id) + "\t Binary :" + binaryToDecimal(id.intValue(), 53));
                Thread.sleep(Integer.MAX_VALUE);


            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();


        Thread.sleep(3000);

        List<MarkWord> markWords = getMarkWords();

        super.printEasyRead(markWords);

        printType(markWords);

        super.printLayout();

        Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();

        for (Map.Entry<Thread, StackTraceElement[]> threadEntry : allStackTraces.entrySet()) {
            System.out.println(threadEntry.getKey().getId() + " name :" + threadEntry.getKey().getName());
        }

    }
}
